package main

import "fmt"

func main() {
	/*
		1.数组 array:
			存储一组相同数据类型的数据结构
				特点：定长

		2.切片 slice:
			同数组类似，也叫做变长数组或者动态数组
				特点：变长

			是一个拥有相同类型元素的可变长度的序列，它是基于数组类型做的一层封装。
			它非常灵活，支持自动扩容。
			是一个引用类型的容器，指向了一个底层数组

		3.make()
			func make(t Type, size ...IntegerType) Type

			第一个参数：类型
				slice, map, channel
			第二个参数：长度
				实际存储元素的数量
			第三个元素：容量 cap
				最多能存储的元素的数量

		4.append()：专门用于向切片的尾部追加元素
			slice = append(slice, elem1, elem2)
			slice = append(slice, anotherSlice...) // 不加"..."会认为是在添加单个元素，报错

		5.copy()：用于复制一个切片
			copy(destslice, srcslice []T) int //返回实际发生复制的元素个数

		6.删除元素：
			Go语言中并没有删除切片元素的专用方法
			要从切片 a 中删除索引为 index 的元素，操作方法是
				a = append(a[:index], a[index+1:]...)

		7.注：
			（1）切片是引用类型，不支持直接比较，只能和 nil 比较
			（2）对切片再执行切片表达式时（切片再切片），新的切片的上限边界是原切片的容量（cap），而不是长度（len）

	*/
	//1.数组
	arr := [4]int{1, 2, 3, 4} // 定长
	fmt.Println(arr)          //[1 2 3 4]

	//2.切片
	var s1 []int
	fmt.Println(s1) //[]

	s2 := []int{1, 2, 3, 4} // 变长
	fmt.Println(s2)
	fmt.Printf("%T,%T\n", arr, s2) //[4]int,[]int

	s3 := make([]int, 3, 8)
	fmt.Println(s3)
	fmt.Printf("容量：%d,长度：%d\n", cap(s3), len(s3))
	s3[0] = 1
	s3[1] = 2
	s3[2] = 3
	fmt.Println(s3)
	//fmt.Println(s3[3]) //index out of range [3] with length 3

	fmt.Println("-----------------------")
	// append()
	s4 := make([]int, 0, 5)
	fmt.Println(s4) //[]
	s4 = append(s4, 1, 2)
	fmt.Println(s4) //[1 2]
	s4 = append(s4, 3, 4, 5, 6, 7)
	fmt.Println(s4) //[1 2 3 4 5 6 7 ]

	s4 = append(s4, s3...)
	fmt.Println(s4) //[1 2 3 4 5 6 7 1 2 3]

	//遍历切片
	for i := 0; i < cap(s4); i++ { // 一定是 len()，而不是cap()
		fmt.Print(s4[i], "\t")
	}
	fmt.Println()

	for _, value := range s4 {
		fmt.Print(value, "\t")
	}
	fmt.Println()

	//复制切片
	c := []int{0, 1, 2}
	d := make([]int, 2, 2)
	copy(d, c)          //copy只会复制 d 和 c 中长度最小的
	fmt.Println(d)      //[0 1]
	fmt.Println(len(d)) //2
	fmt.Println(cap(d)) //2

}
